package com.elbis.business.controller.player;

import java.io.Serializable;
import java.sql.Date;
import java.util.ArrayList;
import java.util.GregorianCalendar;
import java.util.List;

import javax.annotation.PostConstruct;
import javax.faces.event.AjaxBehaviorEvent;
import javax.faces.event.ValueChangeEvent;

import org.apache.log4j.Logger;

import com.elbis.action.input.ErrorMessages;
import com.elbis.action.output.InformativeMessages;
import com.elbis.business.controller.LoginController;
import com.elbis.business.controller.msg.FormFields;
import com.elbis.business.entity.Game;
import com.elbis.business.entity.Gamer;
import com.elbis.business.entity.locale.City;
import com.elbis.business.entity.locale.Country;
import com.elbis.business.entity.locale.Language;
import com.elbis.business.entity.messages.ErrorMessage;
import com.elbis.business.manager.ManageGamer;
import com.elbis.business.manager.MessageManager;
import com.elbis.business.util.ErrorMessageUtil;

public class GamerController implements Serializable {

	private static final long serialVersionUID = 4896923799079416248L;

	private static final Logger logger = Logger
			.getLogger(GamerController.class);

	private String email;

	private String currentPassword;

	private String newPassword;

	private String passwordRepeat;

	private String name;

	private String surname;

	private String nationality;

	private String day;

	private String month;

	private String year;

	private Country country;

	private City city;

	private Language language;

	private List<Game> games;

	private Game newGame;

	private Game removedGame;

	private LoginController loginBean;

	private Gamer gamer;

	@PostConstruct
	public void init() {
		if (loginBean == null) {
			ErrorMessageUtil.addErrorMessage(MessageManager.getErrorMessage(
					ErrorMessages.SYSTEM_ERROR).getMessage());
			logger.error("Gamer bean called with NULL login value.");
			return;
		}
		gamer = loginBean.getCurrentGamer();
		email = gamer.getEmail();
		currentPassword = gamer.getPassword();
		name = gamer.getName();
		surname = gamer.getSurname();
		nationality = gamer.getNationality();
		country = gamer.getCountry();
		city = gamer.getCity();
		language = gamer.getLanguage();
		if (gamer.getDateOfBirth() != null) {
			GregorianCalendar calendar = new GregorianCalendar();
			calendar.setTime(gamer.getDateOfBirth());
			day = String.valueOf(calendar.get(GregorianCalendar.DAY_OF_MONTH));
			month = String.valueOf(calendar.get(GregorianCalendar.MONTH) + 1);
			year = String.valueOf(calendar.get(GregorianCalendar.YEAR));
		}
		if (gamer.getGames() != null && !gamer.getGames().isEmpty()) {
			games = new ArrayList<Game>(gamer.getGames());
		} else {
			games = new ArrayList<Game>();
		}
	}

	public String updateGamer() {
		// handle password update
		if (currentPassword != null && !currentPassword.isEmpty()) {
			if (!gamer.getPassword().equals(currentPassword)) {
				ErrorMessageUtil.addErrorMessage(
						FormFields.CURRENT_PASSWORD,
						MessageManager.getErrorMessage(
								ErrorMessages.INCORRECT_CURRENT_PASSWORD)
								.getMessage());
				return null;
			}
			// null or invalid length check
			if (!isNewPasswordValid() || !isPasswordRepeatValid()) {
				ErrorMessage passMessage = MessageManager
						.getErrorMessage(ErrorMessages.INVALID_PASSWORD_VALUE);
				ErrorMessageUtil.addErrorMessage(FormFields.NEW_PASSWORD,
						passMessage.getMessage());
				ErrorMessageUtil.addErrorMessage(FormFields.PASSWORD_REPEAT,
						passMessage.getMessage());
				return null;
			}
			// check if new passwords match
			if (!isNewPasswordMatchRepeat()) {
				ErrorMessage passMessage = MessageManager
						.getErrorMessage(ErrorMessages.ENTERED_PASSWORDS_DO_NOT_MATCH);
				ErrorMessageUtil.addErrorMessage(FormFields.NEW_PASSWORD,
						passMessage.getMessage());
				ErrorMessageUtil.addErrorMessage(FormFields.PASSWORD_REPEAT,
						passMessage.getMessage());
				return null;
			}
			// check if the new password is different than the current one
			if (newPassword.equals(currentPassword)) {
				ErrorMessageUtil.addErrorMessage(
						FormFields.NEW_PASSWORD,
						MessageManager.getErrorMessage(
								ErrorMessages.OLD_AND_NEW_PASSWORD_SAME)
								.getMessage());
				return null;
			}
		}

		Date dateOfBirth = null;
		if (day != null && month != null && year != null) {
			try {
				int dayint = Integer.valueOf(day);
				int monthint = Integer.valueOf(month);
				int yearint = Integer.valueOf(year);
				GregorianCalendar calendar = new GregorianCalendar();
				calendar.set(yearint, monthint - 1, dayint);
				dateOfBirth = new Date(calendar.getTimeInMillis());
			} catch (NumberFormatException nfe) {
				if (logger.isInfoEnabled()) {
					logger.info("Day, month or year value is non-numeric. ["
							+ day + ", " + month + ", " + year + "]");
				}
			}
		}

		gamer.setCity(city);
		gamer.setCountry(country);
		gamer.setLanguage(language);
		gamer.setDateOfBirth(dateOfBirth);
		gamer.setName(name);
		gamer.setSurname(surname);
		gamer.setNationality(nationality);
		gamer.setGames(games);
		if (isNewPasswordValid()) {
			gamer.setPassword(newPassword);
		}
		ManageGamer mg = new ManageGamer();
		mg.update(gamer);
		if (logger.isInfoEnabled()) {
			logger.info("Gamer profile updated.");
		}
		ErrorMessageUtil.addInformativeMessage(FormFields.INFO, MessageManager
				.getInformativeMessage(InformativeMessages.PROFILE_UPDATED)
				.getMessage());
		return null;
	}

	public void addGame(AjaxBehaviorEvent e) {
		if (newGame != null && !games.contains(newGame)) {
			games.add(newGame);
		}
	}

	public void removeGame(AjaxBehaviorEvent e) {
		if (games != null && removedGame != null) {
			games.remove(removedGame);
		}
	}

	public boolean isNewPasswordValid() {
		return (newPassword != null && newPassword.length() >= FormFields.MIN_PASSWORD_LENGTH);
	}

	public boolean isPasswordRepeatValid() {
		return (passwordRepeat != null && passwordRepeat.length() >= FormFields.MIN_PASSWORD_LENGTH);
	}

	public boolean isNewPasswordMatchRepeat() {
		return isNewPasswordValid() && isPasswordRepeatValid()
				&& newPassword.equals(passwordRepeat);
	}

	public Gamer getGamer() {
		return gamer;
	}

	public void setGamer(Gamer gamer) {
		this.gamer = gamer;
	}

	public List<City> getCities() {
		List<City> cities = null;
		if (country != null) {
			cities = country.getCities();
		}
		return cities;
	}

	public void countryChanged(ValueChangeEvent e) {
		Country newCountry = (Country) e.getNewValue();
		country = newCountry;
	}

	public List<String> getDays() {
		List<String> days = new ArrayList<String>();
		for (int i = 1; i <= 31; i++) {
			days.add(String.valueOf(i));
		}
		return days;
	}

	public List<String> getMonths() {
		List<String> months = new ArrayList<String>();
		for (int i = 1; i <= 12; i++) {
			months.add(String.valueOf(i));
		}
		return months;
	}

	public List<String> getYears() {
		List<String> years = new ArrayList<String>();
		GregorianCalendar calendar = new GregorianCalendar();
		int currentYear = calendar.get(GregorianCalendar.YEAR);
		for (int i = currentYear; i > currentYear - 50; i--) {
			years.add(String.valueOf(i));
		}
		return years;
	}

	public String getEmail() {
		return email;
	}

	public void setEmail(String email) {
		this.email = email;
	}

	public String getCurrentPassword() {
		return currentPassword;
	}

	public void setCurrentPassword(String currentPassword) {
		this.currentPassword = currentPassword;
	}

	public String getNewPassword() {
		return newPassword;
	}

	public void setNewPassword(String newPassword) {
		this.newPassword = newPassword;
	}

	public String getPasswordRepeat() {
		return passwordRepeat;
	}

	public void setPasswordRepeat(String passwordRepeat) {
		this.passwordRepeat = passwordRepeat;
	}

	public String getName() {
		return name;
	}

	public void setName(String name) {
		this.name = name;
	}

	public String getSurname() {
		return surname;
	}

	public void setSurname(String surname) {
		this.surname = surname;
	}

	public String getNationality() {
		return nationality;
	}

	public void setNationality(String nationality) {
		this.nationality = nationality;
	}

	public String getDay() {
		return day;
	}

	public void setDay(String day) {
		this.day = day;
	}

	public String getMonth() {
		return month;
	}

	public void setMonth(String month) {
		this.month = month;
	}

	public String getYear() {
		return year;
	}

	public void setYear(String year) {
		this.year = year;
	}

	public Country getCountry() {
		return country;
	}

	public void setCountry(Country country) {
		this.country = country;
	}

	public City getCity() {
		return city;
	}

	public void setCity(City city) {
		this.city = city;
	}

	public Language getLanguage() {
		return language;
	}

	public void setLanguage(Language language) {
		this.language = language;
	}

	public LoginController getLoginBean() {
		return loginBean;
	}

	public void setLoginBean(LoginController loginBean) {
		this.loginBean = loginBean;
	}

	public List<Game> getGames() {
		return games;
	}

	public void setGames(List<Game> games) {
		this.games = games;
	}

	public Game getNewGame() {
		return newGame;
	}

	public void setNewGame(Game selectedGame) {
		this.newGame = selectedGame;
	}

	public Game getRemovedGame() {
		return removedGame;
	}

	public void setRemovedGame(Game removedGame) {
		this.removedGame = removedGame;
	}

}
